rm(list = ls(all = TRUE))
setwd("C:\\Users\\lenovo\\Desktop\\R\\神经网络_R语言实现")
#3.1 DNN简介
#大数据处理技术的基础设施与GPU的到来为浅层神经网络的优化提供了物质基础
#主要是过拟合、梯度消失的问题

#简单地说，DNN的本质是多层神经网络
#通过增加更多的层、每层增加更多的神经元，
#可以提高训练数据模型的专业化，
#但也相对降低了它关于测试数据集的性能

#有以下3类DNN

#深度信念网络
#Deep Belief Network，DBN
#一种前馈神经网络，数据从一个层流向另一个层，并且不再返回
#通过增加多个隐含层来提升复杂度

#受限玻尔兹曼机
#Restricted Boltzmann Machine，RBM
#包含单个隐含层，组内的节点之间没有连接
#神经网络的一个简单的多层感知机模型

#循环神经网络
#Recurrent Neural Network,RNN
#长短期记忆
#Long Short Term Memory, LSTM

#几乎所有的机器学习算法都表明它们在识别原始输入数据的特征过程中
#存在限制
#深度学习去除了通过人工解决这一步的过程，
#依靠训练过程通过输入样本发现最有用的模型。
#因此，与机器学习提供的其它解决方法相比，
#使神经网络特别有用的是它的泛化能力

#3.2 用于DNN的R语言
install.packages("MXNet")#not avaliable for 4.0.2
install.packages("darch")#not avaliable for 4.0.2
install.packages("deepnet")
#deepnet是一个相对较小但十分强大的添加包
#nn.train用于训练反向传播神经网络中的单个或多个隐含层
#nn.predict用于预测训练神经网络的新样本
#dpn.dnn.train用于训练一个DNN，权重由DBN初始化得到
#rbm.train用于训练一个RBM

install.packages("h2o")
#包含建立广义线性回归、K均值、朴素贝叶斯、
#主成分分析、随机森林和深度学习（多层神经网络模型）的函数

install.packages("nnet")
install.packages("neuralnet")
#以上两个包为R中用于管理神经网络的常用包

install.packages("keras")
install.packages("tensorflow")
#搜索或Google产品

#3.3 通过neuralnet建立多层神经网络
#目的：建立一个多层神经网络，
#根据其他17个变量的值预测学校是公立大学还是私立大学

#数据加载
#install.packages("ISLR")
library(ISLR)
#install.packages("neuralnet")
library(neuralnet)
data = College
View(data)


#对数据进行标准化
#通过标准化，数据的单位被消除，使你能够简单地从不同的角度比较数据
#最小-最大法，特征标准化
max_data <- apply(data[,2:18], 2, max)
min_data <- apply(data[,2:18], 2, min)
data_scaled <- scale(data[,2:18], center = min_data,
                     scale = max_data - min_data)

#将Factor类型转换为数值变量
Private = as.numeric(College$Private)-1
#重构具有该变量以及剩余17个经适当标准化后的变量的数据集
data_scaled = cbind(Private, data_scaled)

#将数据集按照70：30划分
index = sample(1:nrow(data),round(0.70*nrow(data)))
train_data <- as.data.frame(data_scaled[index,])
test_data <- as.data.frame(data_scaled[-index,])

#使用names获得所有的变量名
n = names(train_data)
#设置用于构建神经网络的公式
f <- as.formula(paste("Private ~", paste(n[!n %in% "Private"],
                      collapse = " + ")))

#数据准备完成
#构建神经网络
deep_net = neuralnet(f, data = train_data, hidden = c(5,3),
                     linear.output = F)
plot(deep_net)

#验证其预测能力，用compute函数
predicted_data <- compute(deep_net, test_data[,2:18])
print(head(predicted_data$net.result))
#用sapply将函数四舍五入到可用的类别
predicted_data$net.result <- 
  sapply(predicted_data$net.result, round, digits = 0)

#建立混淆矩阵并评估
table(test_data$Private, predicted_data$net.result)

#获取样本数
table(predicted_data$net.result)

Acc = (53+169)/(53+169+5+6)
Acc

#3.4 使用H2O对DNN进行训练和建模
#H2O是一个开源、利用内存、可扩展的机器学习平台和AI平台，
#用于建立大数据模型，并实现高效准确度方法的预测
#install.packages("h2o")

#支撑添加包安装
install.packages("RCurl")
install.packages("bitops")
install.packages("rjson")
install.packages("jsonlite")
install.packages("statmod")
install.packages("tools")
install.packages("data.table")

library(h2o)
#初始化h2o引擎
#设置最大内存2GB，双核并行
c1 = h2o.init(max_mem_size = "2G",
              nthreads = 2,
              ip = "localhost",
              port = 54321)
data(iris)
summary(iris)

#使用CPU建立DNN模型，
#在H2OFrame上建立一个前馈多层ANN
#参数hidden用于设置隐含层的个数以及每个隐含层的神经元个数
#export_weights_and_biases = T 用于返回H2OFrame中存储的权重和偏差
#且可以像其他数据框一样被访问以供进一步处理
iris_d1 <- h2o.deeplearning(1:4,5,
           as.h2o(iris),hidden = c(5,5),
           export_weights_and_biases = T)
#隐含层神经元个数不能太少，避免难以捕捉
#个数不能太多，避免过拟合
#每个隐含层的神经元个数应该接近输入层和输出层的神经元个数，
#可能是两者的均值
#每个隐含层的神经元个数不应该超过输入层神经元个数的两倍，
#否则可能会过拟合

iris_d1
plot(iris_d1)
#该图展示了训练分类误差与epoch的关系，可以看到，在epoch的过程中，
#梯度下降，误差下降
#数据集迭代（streamed）的次数可以是小数，默认设置为10

#简单地打印3种鸢尾花的权重和偏差的汇总
h2o.weights(iris_d1, matrix_id = 1)
h2o.weights(iris_d1, matrix_id = 2)
h2o.weights(iris_d1, matrix_id = 3)
h2o.biases(iris_d1, vector_id = 1)
h2o.biases(iris_d1, vector_id = 2)
h2o.biases(iris_d1, vector_id = 3)

#查看serota类别的权重和偏差
plot(as.data.frame(h2o.weights(iris_d1, matrix_id = 1))[,1])

#调用混淆矩阵
h2o.confusionMatrix(iris_d1)
#注意到serota完全分类正确

#看一下原始数据
pairs(iris[1:4], main = "Scatterplot matrices of Iirs Data",pch = 21,
      bg = c("red","green3","blue")[unclass(iris$Species)])
#出现问题的原因在于，serota的数据与其他没有交集，
#而versicolor与virginica显示出重叠的边界

#根据花瓣和萼片的大小来评估模型对花卉种类分类时的准确性
h2o.hit_ratio_table(iris_d1)

#计算决定系数R方
h2o.r2(iris_d1)

#为了确认该分类较好，一般采用线性回归模型对比

#建立线性回归模型
m = iris.lm <- h2o.glm(x = 2:5, y = 1, training_frame = as.h2o(iris))
h2o.r2(m)

#有一些重要的分析参数，见书本
#activation：激活函数。必须是Tanh、TanhWithDropout、Rectifier、
#RectifierWithDropout、Maxout、MaxoutWithDropout。默认为Rectifier
#hidden：隐含层大小，默认为[200，200]
#epoches：迭代（streamed）次数，可以为小数，默认为10
#rho:自适应学习率时间衰减因子（类似于先验更新，默认为0.99）
#rate_annealing：学习率退火，由rate/（1+rate_annealing*samples)给出，
#默认为1e-6
#input_dropout_ratio：输入层丢弃率，可以改进泛化，尝试0.1、0.2，
#默认为0
#hidden_dropout_ratio：隐含层丢弃率可以改善泛化。
#为每个隐含层指定一个值，默认为0.5
#l1：L1正则化可以增加稳定性和提高泛化能力，
#使得许多权重变为0。默认为0
#l2：L2正则化可以增加稳定性和提高泛化能力，
#使得许多权重变很小。默认为0


###一些常用函数：###

#predict.H2Omodel
#返回一个H2OFrame对象，包含概率和默认的预测值

#h2o.deepwater
#使用多个本地GPU后端机建立一个深度学习模型。
#在包含多个数据源的H2OFrame中建立DNN

#as.data.frame.H2OFrame
#将H2OFrame转换为数据框

#h2o.confusionMatrix
#返回一个分类模型的混淆矩阵

#print.H2OFrame
#打印H2OFrame

#h2o.saveModel
#将h2o模型对象保存到磁盘

#h2o.importFile
#将文件导入h2o

#3.5 使用H2O建立深度自动编码器
#自动编码器是基于神经网络的无监督学习方法
#h2o可以使用自动编码器检测异常值
#为了训练这样一个模型，可以使用同样的函数h2o.deeplearning
#这里仅使用训练数据，不包含测试集和标签
anomaly_model <- h2o.deeplearning(1:4,
                                  training_frame = as.h2o(iris),
                                  activation = "Tanh",
                                  autoencoder = TRUE,
                                  #通过制定参数auroencoder来使用深度自动编码器
                                  hidden = c(50,20,50),
                                  sparse = TRUE,
                                  l1 = 1e-4,
                                  epochs = 100)

#可以选用不同层的隐含神经元个数。如果一个整数值，则称之为
#朴素自动编码（native autoencoder）